package JET.graphics.swing;

import JET.Centers.Graphics.GraphicMode;
import JET.physics.bodies.SpringBody;
import JET.geom.Rect2d;
import JET.geom.Sec2d;
import JET.geom.Vec2d;

import java.awt.Color;
import java.awt.Dimension;

import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;

import java.awt.geom.Ellipse2D;
import java.awt.geom.Line2D;
import java.awt.geom.Rectangle2D;

import javax.swing.JScrollPane;
import javax.swing.JViewport;

import JET.physics.*;
import JET.Constants;
import JET.Centers.ControlCenter;

import JET.MouseStuff.MouseMode;
import JET.Scene;
import JET.geom.BezierCurve;
import JET.graphics.GeomCursorTarget;
import JET.graphics.GraphicPanel;
import JET.graphics.elements.Face;
import JET.graphics.elements.SceneDrawable;
import JET.mygui.MyGuiHelper;
import JET.physics.Spring;
import JET.physics.bodies.Body;
import JET.physics.bodies.RigidBody;
import JET.physics.engine.JETContext;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import javax.imageio.ImageIO;
import javax.swing.JPanel;
//import rasterizer.MyRaster;


/**
 *
 * @author 057Ry
 */
public final class SwingGraphicPanel extends JPanel implements GraphicPanel, /*CenterTabsPaneTab,*/ Constants
{
    static final ControlCenter CC = ControlCenter.getInstance();
    
    private Graphics2D g2d;

    private double dX,dY;// dX is distance between scene vertical edgeds to nearest
                         // graphic panel edges (note: not viewpoer ones),
                         // and so is dY in horiz.

    private double ltvpdX, ltvpdY; // when engine area is smaller Than View Port of scrollPane theese variables are used to center the scene over the screen/viewport.
                                   // ltvpdX stands for Length To ViewPort dX - distance between left viewport edge to left scene(MainBound) edge,
                                   // and so the ltvpdY stands ... ;)

    public static BufferedImage tex, img;
    public static int[] img_clear;
    
//    private double viewScale = 1;
//    private final double dViewScale = 0.01;
    private Dimension originalSize;
            
//    private double mainGriddX = 50;
//    private double mainGriddY = 50;
    private Color mainGridColor = START_MAIN_GRID_COLOR;
    
//    private double helpGriddX = 5;
//    private double helpGriddY = 5;
    private Color helpGridColor = START_HELP_GRID_COLOR;

    private static int drawnMassesCount = 0;
    private static int drawnSpringsCount = 0;
    private static int drawnWallsCount = 0;
    private static int drawnSpringBodiesCount = 0;

    protected double mainGriddX = 50;
    protected double mainGriddY = 50;

    protected double helpGriddX = 5;
    protected double helpGriddY = 5;

    protected double viewScale = 1.;

    public String sceneName;
    public Scene scene;
    public JETContext engine;

    public final BezierCurve        bezier = new BezierCurve();
    public final ArrayList<Vec2d>   bVecs = new ArrayList<Vec2d>();


    public SwingGraphicPanel(String sceneName) {
        setBackground( Color.WHITE );
        this.setFocusable(true);
        setDoubleBuffered(false);

        this.scene = CC.getScene(sceneName);
        //this.engine = scene.getEngine() ;

        setStartingDimension();

        try {
            tex = ImageIO.read( SwingGraphicPanel.class.getResource("../../Images/box2.jpg") );
        } catch(Exception e) {e.printStackTrace();}
    }

    @Override
    public double getHelpGriddX() {
        return helpGriddX;
    }

    @Override
    public double getHelpGriddY() {
        return helpGriddY;
    }

    @Override
    public double getMainGriddX() {
        return mainGriddX;
    }

    @Override
    public double getMainGriddY() {
        return mainGriddY;
    }

    @Override
    public Rectangle2D getActionFrameSideBoxRect(Body body, int index)
    {
        BoundingArea ba = body.getBoundingArea();

        double space = 2.5 * viewScale;

        double x1 = engineToScrX( ba.getMinX() ) -space;
        double y1 = engineToScrY( ba.getMaxY() ) -space;
        double x2 = engineToScrX( ba.getMaxX() ) +space;
        double y2 = engineToScrY( ba.getMinY() ) +space;

        double width = x2-x1;
        double height = y2-y1;
        final double scaleBoxSize = ACTION_FRAME_SIDE_BOX_SIZE;

        if (index == 0) // Action Frame Rect
        {
            return new Rectangle2D.Double(x1, y1, x2-x1, y2-y1);
        }
        else if (index == 1)  // Top Left Rect
        {
            double x = x1 - scaleBoxSize;
            double y = y1 - scaleBoxSize;
            return new Rectangle2D.Double(x,y, scaleBoxSize*2, scaleBoxSize*2);
        }
        else if (index == 2) // Middle Top Rect
        {
            double x = x1 + width/2. - scaleBoxSize;
            double y = y1 - scaleBoxSize;

            return new Rectangle2D.Double(x,y, scaleBoxSize*2, scaleBoxSize*2);
        }
        else if (index == 3) // Top Right
        {
            double x = x2 - scaleBoxSize;
            double y = y1 - scaleBoxSize;
            return new Rectangle2D.Double(x,y, scaleBoxSize*2, scaleBoxSize*2);
        }
        else if (index == 4) // Right Middle
        {
            double x = x2 - scaleBoxSize;
            double y = y1 + height/2. - scaleBoxSize;
            return new Rectangle2D.Double(x,y, scaleBoxSize*2, scaleBoxSize*2);
        }
        else if (index == 5) // Bottom Right
        {
            double x = x2 - scaleBoxSize;
            double y = y2 - scaleBoxSize;
            return new Rectangle2D.Double(x,y, scaleBoxSize*2, scaleBoxSize*2);
        }
        else if (index == 6) // Bottom Middle
        {
            double x = x1 + width/2. - scaleBoxSize;
            double y = y2 - scaleBoxSize;
            return new Rectangle2D.Double(x,y, scaleBoxSize*2, scaleBoxSize*2);
        }
        else if (index == 7) // Bottom Left
        {
            double x = x1 - scaleBoxSize;
            double y = y2 - scaleBoxSize;
            return new Rectangle2D.Double(x,y, scaleBoxSize*2, scaleBoxSize*2);
        }
        else if (index == 8) // Left Middle
        {
            double x = x1 - scaleBoxSize;
            double y = y1 + height/2. - scaleBoxSize;
            return new Rectangle2D.Double(x,y, scaleBoxSize*2, scaleBoxSize*2);
        }

        return null;
    }

    public GraphicsDevice getGraphicsDevice() {
        GraphicsEnvironment environment =
            GraphicsEnvironment.getLocalGraphicsEnvironment();
        return environment.getDefaultScreenDevice();
    }

    private void setStartingDimension()
    {
        this.dX = scene.getJETContext().getMainBound().getWidth();
        this.dY = scene.getJETContext().getMainBound().getHeight();

        originalSize = new Dimension((int)(scene.getJETContext().getMainBound().getWidth() + 2*dX),
                                       (int)(scene.getJETContext().getMainBound().getHeight() + 2*dY)
                                    );
        this.setSize(originalSize);
        this.setMaximumSize(originalSize);
        this.setPreferredSize(originalSize);
        this.setMinimumSize(originalSize);

        // start values of ltvpdX and ltvpdY are sX and dY ;]
        this.ltvpdX = dX;
        this.ltvpdY = dY;
    }

    private double getSceneLeftEdgeX()
    {
        return ltvpdX;
    }

    private double getSceneTopEdgeY()
    {
        return ltvpdY;
    }

    public void centerView()
    {
        if ( this.getParent() != null )
        {
            JViewport vp = (JViewport)this.getParent();
            vp.updateUI();
            
            int x = (int)( this.getWidth()/2.  - vp.getWidth()/2. );
            int y = (int)( this.getHeight()/2. - vp.getHeight()/2. );

            Point centeredViewPosition = new Point(x, y);
            vp.setViewPosition(centeredViewPosition);
        }
    }

    /**
     * Moves viewport so vec becomes center point of it.
     *
     * @param vec vector you want to be centered on the screen (in engine system).
     */
    public void centerViewToVec(Vec2d vec)
    {
        if (this.getParent() != null)
        {
            JViewport vp = (JViewport)this.getParent();

            double oldSx = engineToScrX(vec.getX());
            double oldSy = engineToScrY(vec.getY());

            double newSx = vp.getViewPosition().x + vp.getWidth()/2;
            double newSy = vp.getViewPosition().y + vp.getHeight()/2;

            double moveX = newSx - oldSx;
            double moveY = newSy - oldSy;

            Point viewportPos = vp.getViewPosition();
            Point newViewPos = new Point( (int)(viewportPos.getX()-moveX), (int)(viewportPos.getY()-moveY) );
            vp.setViewPosition( newViewPos );
        }
    }

    public void printDimensionsInfo()
    {
        if ( this.getParent() != null )
        {
            JViewport vp = (JViewport)this.getParent();
            System.out.println("vp.getWidth() = "+vp.getWidth());
            System.out.println("vp.getHeight() = "+vp.getHeight());

            System.out.println("vp.getViewSize().getWidth() = "+vp.getViewSize().getWidth());
            System.out.println("vp.getViewSize().getHeight() = "+vp.getViewSize().getHeight());
            
            System.out.println("vp.getViewSize().getWidth() = "+vp.getViewSize().getWidth());
            System.out.println("vp.getViewSize().getHeight() = "+vp.getViewSize().getHeight());

            System.out.println("vp.getExtentSize().getWidth() = "+vp.getExtentSize().getWidth());
            System.out.println("vp.getExtentSize().getHeight() = "+vp.getExtentSize().getHeight());

        }
        else System.out.println("ViewPort is null - dont know its dimensions...");

        System.out.println("gp.getWidth() = "+this.getWidth());
        System.out.println("gp.getHeight() = "+this.getHeight());
        
        System.out.println("scene.getWidth() = "+scene.getJETContext().getMainBound().getWidth());
        System.out.println("scene.getHeight() = "+scene.getJETContext().getMainBound().getHeight());
    }
    
    public double fixVertical(double y)
    {
        return y*-1 + this.getHeight()-1;
    }

    @Override
    public void paintComponent(Graphics g)
    {
        g2d = (Graphics2D)g;

        Rectangle vRect = getVisibleRect();
        g2d.setColor(Color.WHITE);

        g2d.fill( new Rectangle2D.Double(vRect.getX(), vRect.getY(), vRect.getWidth(), vRect.getHeight()) );

        //// TEXTURING tests

//        if (scene.getJETContext().getSpringBodyList().size()>0)
//        {
//            JViewport vp = (JViewport)this.getParent();
//            double vpx = vp.getViewPosition().getX();
//            double vpy = vp.getViewPosition().getY();
//
//            if (img!=null)
//            {
//                img.getGraphics().setColor(Color.WHITE);
//                img.getGraphics().fillRect(0,0,img.getWidth(), img.getHeight());
//            }
//
//            for(int i=0; i<scene.getJETContext().getSpringBodyList().size(); i++)
//            {
//                SpringBody texsb = scene.getJETContext().getSpringBodyList().get(i);
//                if (img==null)
//                {
//                    GraphicsEnvironment environment = GraphicsEnvironment.getLocalGraphicsEnvironment();
//                    GraphicsDevice device = environment.getDefaultScreenDevice();
//                    GraphicsConfiguration config = device.getDefaultConfiguration();
//                    //img = config.createCompatibleImage(vp.getWidth(), vp.getHeight(), Transparency.TRANSLUCENT);
//                    //img_clear = new int[vp.getWidth()*vp.getHeight()*4];
//                    img = config.createCompatibleImage(vp.getWidth(), vp.getHeight(), Transparency.OPAQUE);
//                    img_clear = new int[vp.getWidth()*vp.getHeight()*3];
//                }
//
//                //img.getRaster().setPixels(0,0, img.getRaster().getWidth(), img.getRaster().getHeight(), img_clear);
//
//
//                ArrayList<Mass> massList = texsb.getMassList();
//
//                double x1 = engineToScrX( massList.get(0).getPosition().x )-vpx;
//                double y1 = engineToScrY( massList.get(0).getPosition().y )-vpy;
//                double x2 = engineToScrX( massList.get(1).getPosition().x )-vpx;
//                double y2 = engineToScrY( massList.get(1).getPosition().y )-vpy;
//                double x3 = engineToScrX( massList.get(2).getPosition().x )-vpx;
//                double y3 = engineToScrY( massList.get(2).getPosition().y )-vpy;
//                double x4 = engineToScrX( massList.get(3).getPosition().x )-vpx;
//                double y4 = engineToScrY( massList.get(3).getPosition().y )-vpy;
//
//                double tx1 = 0;
//                double ty1 = 0;
//                double tx2 = tex.getWidth()-1;
//                double ty2 = 0;
//                double tx3 = tex.getWidth()-1;
//                double ty3 = tex.getHeight()-1;
//                double tx4 = 0;
//                double ty4 = tex.getHeight()-1;
//
//                MyRaster.texTriangle(x1,y1, x2,y2, x3,y3,
//                                     tx1,ty1, tx2,ty2, tx3,ty3,
//                                     img, tex);
//                MyRaster.texTriangle(x3,y3, x4,y4, x1,y1,
//                                     tx3,ty3, tx4,ty4, tx1,ty1,
//                                     img, tex);
//            }
//            g2d.drawImage(img, (int)vpx, (int)vpy, null);
//
//        }

        //// end of TEXTURING tests

        // siatka
        if ( scene.GC.isDrawHelpGrid() ) drawHelpGrid();
        if ( scene.GC.isDrawMainGrid() ) drawMainGrid();
        
        // glowna banda
        drawEngineMainBound();

        // rigidBodies
        Collection<RigidBody> rbCol = scene.getJETContext().getRigidBodyListSync();
        synchronized(rbCol) {
            for(RigidBody rb : rbCol)
            {
                drawRigidBody(rb);
            }
        }

        // springBodies
        Collection<SpringBody> sbCol = scene.getJETContext().getSpringBodyListSync();
        synchronized(sbCol) {
            for(SpringBody sb : sbCol)
            {
                drawSpringBody(sb);
            }
        }

        // Scene drawables
        drawSceneDrawables();

        // Selection
        drawSelectionGroup();
        drawTempSelectionGroup();

        // Engine Springs
        if (scene.GC.isDrawSprings2d())
            for(Spring spring : scene.getJETContext().getSpringList())
                drawEngineSpring(spring);

        // Engine Rotary Springs
        if (scene.GC.isDrawSprings2d())
            for(RSpring rSpring : scene.getJETContext().getRSpringList())
                drawEngineRSpring(rSpring);
        
        // Action Frame
        if (scene.EC.currentBody!=null && scene.GC.isDrawActionFrame())
            drawBodyActionFrame(scene.EC.currentBody);

//        // scene items
//        Collection<SceneItem> siCol = scene.getSceneItemsListSync();
//        synchronized(siCol) {
//            for(SceneItem si : siCol) {
//                Collection<SpringBody> springBodyCol = si.getEngine().getSpringBodyListSync();
//                synchronized(springBodyCol) {
//                    for(SpringBody sb : springBodyCol) {
//                        drawSpringBody(sb);
//
//                        if (sb.equals(scene.EC.currentSpringBody) && scene.GC.isDrawActionFrame())
//                        drawSpringBodyActionFrame(sb);
//                    }
//                }
//
//                Collection<Spring> springCol = si.getEngine().getSpringListSync();
//                synchronized(springCol) {
//                    for(Spring s : springCol)
//                        drawEngineSpring(s);
//                }
//
//                Collection<RSpring> rSpringCol = si.getEngine().getRSpringListSync();
//                synchronized(rSpringCol) {
//                    for(RSpring s : rSpringCol)
//                        drawEngineRSpring(s);
//                }
//            }
//        }


//        if ( scene.GC.isDrawSpringBodyCollisions() && scene.getJETContext().isFindCollisions() ) {
            drawSpringBodyWalabersCollisions();
            drawRigidBodyWalabersCollisions();
//        }

//        // TEMP bezier drawing
//        if (!scene.getEngine().getSpringBodyList().isEmpty()) {
//            SpringBody sb = scene.getEngine().getSpringBodyList().get(0);
//            if (sb.getMassList().size()>2)
//            {
////                bVecs.clear();
////
////                Collection<Mass> massCol = sb.getMassListSync();
////                synchronized(massCol) {
////                    for(Mass m : massCol)
////                        bVecs.add(m.getPosition());
////                }
////
////                bezier.setCPoints(bVecs);
////                bezier.build();
////
////                g2d.setColor(Color.ORANGE);
////                Collection<Vec2d> points = bezier.getPointsSync();
////                int i=0;
////                synchronized(points) {
////                    for(Vec2d v : points) {
////                        if (i>10 && i<points.size()-10) {
////                            double x = engineToScrX(v.x);
////                            double y = engineToScrY(v.y);
////                            g2d.fill(new Rectangle2D.Double(x-2,y-2,4,4));
////                        }
////                        i++;
////                    }
////                }
//                ControlCurve curve = new NatCubic();
//                Collection<Mass> massCol = sb.getMassListSync();
//                synchronized(massCol) {
//                    for(Mass m : massCol)
//                        curve.addPoint((int)m.getPosition().x, (int)m.getPosition().y);
//                }
//                curve.paint(g, this);
////            }
//            }
//
//            if (scene.getEngine().getSpringBodyList().size()>1)
//                sb = scene.getEngine().getSpringBodyList().get(1);
//            else
//                sb = null;
//            if (sb!=null&&sb.getMassList().size()>2)
//            {
//                ControlCurve curve = new Bezier();
//                curve = new Bezier();
//                Collection<Mass> massCol = sb.getMassListSync();
//                synchronized(massCol) {
//                    for(Mass m : massCol)
//                        curve.addPoint((int)m.getPosition().x, (int)m.getPosition().y);
//                }
//                g2d.setPaint(Color.BLUE);
//                curve.paint(g, this);
//            }
//
//            if (scene.getEngine().getSpringBodyList().size()>2)
//                sb = scene.getEngine().getSpringBodyList().get(2);
//            else
//                sb = null;
//            if (sb!=null&&sb.getMassList().size()>2)
//            {
//                ControlCurve curve = new Bspline();
//                curve = new Bezier();
//                Collection<Mass> massCol = sb.getMassListSync();
//                synchronized(massCol) {
//                    for(Mass m : massCol)
//                        curve.addPoint((int)m.getPosition().x, (int)m.getPosition().y);
//                }
//                g2d.setPaint(Color.GREEN);
//                curve.paint(g, this);
//            }
//        }
//
//        // /TEMP bezier drawing



        // mouse mode addons
        switch( CC.MC.getMouseMode() )
        {
            case SET_MOVEABLE : drawMouseCatchArea(); break;
            case MOVE_MASSES :
                switch( CC.MC.getMouseModeAlt(CC.MC.getMouseMode())) {
                    case SPECYFIC : drawMouseCatchArea(); break;
                }
                break;
            case ADD_SINGLE_WALL :
                drawMouseCatchArea();
                switch( CC.MC.getMouseSubMode() )
                {
                    case FIND_SECOND_OBJECT : drawAddWall2dLine(); break;
                }
                break;
            case ADD_SINGLE_SPRING :
                drawMouseCatchArea();
                switch( CC.MC.getMouseSubMode() )
                {
                    case FIND_SECOND_OBJECT : drawAddSpring2dLine(); break;
                }
                break;
            case ADD_SINGLE_RSPRING :
                drawMouseCatchArea();
                switch(CC.MC.getMouseSubMode()) {
                    case FIND_SECOND_OBJECT : drawAddRSpring1(); break;
                    case FIND_THIRD_OBJECT : drawAddRSpring2(); break;
                }

                break;
            case CREATE_CIRCLE :
                switch( CC.MC.getMouseSubMode() )
                {
                    case FIND_SECOND_OBJECT : drawCreateCircle(); break;
                }
                break;
            case CREATE_SQUARENET :
                switch( CC.MC.getMouseSubMode() )
                {
                    case FIND_SECOND_OBJECT : drawCreateSquareNet(); break;
                }
                break;
            case SELECT_ALL_ITEMS :
            case SELECT_MASSES :
            case SELECT_SPRINGS :
            case SELECT_RSPRINGS :
            case SELECT_WALLS :
                switch( CC.MC.getMouseSubMode() )
                {
                    case FIND_SECOND_OBJECT : drawSelectionRect(); break;
                }
                break;
            case SELECT_MASSES_IN_ORDER :
                switch( CC.MC.getMouseSubMode() )
                {
                    case FIND_SECOND_OBJECT : drawSelectionInOrder(); break;
                }
                break;
            case ROTATE :
                switch( CC.MC.getMouseSubMode() )
                {
                    case FIND_SECOND_OBJECT : drawRotation(); break;
                }
                break;
            case SCALE :
                switch( CC.MC.getMouseSubMode() )
                {
                    case FIND_SECOND_OBJECT : drawScaling(); break;
                }
                break;
            case COPY_SELECTED_ITEMS :
                drawCopySelectedItems();
                break;
        }

        if ( scene.EC.isDrawCursor() )
        {
            double x = engineToScrX(scene.EC.engCursor.getX());
            double y = engineToScrY(scene.EC.engCursor.getY());
            double r = 4;

            g2d.setPaint(Color.RED);

            if (scene.EC.getCursorTarger() == GeomCursorTarget.MAIN_GRID)
            {
                g2d.draw( new Line2D.Double(x,y-5,x,y+5));
                g2d.draw( new Line2D.Double(x-1,y-5,x-1,y+5));
                g2d.draw( new Line2D.Double(x+1,y-5,x+1,y+5));

                g2d.draw( new Line2D.Double(x-5,y,x+5,y));
                g2d.draw( new Line2D.Double(x-5,y-1,x+5,y-1));
                g2d.draw( new Line2D.Double(x-5,y+1,x+5,y+1));
            }
            else if (scene.EC.getCursorTarger() == GeomCursorTarget.HELP_GRID)
            {
                g2d.draw( new Line2D.Double(x,y-5,x,y+5));
                g2d.draw( new Line2D.Double(x-5,y,x+5,y));
            }
            else if (scene.EC.getCursorTarger() == GeomCursorTarget.MASS)
            {
                g2d.draw( new Ellipse2D.Double(x-r, y-r, r*2, r*2) );
                g2d.draw( new Ellipse2D.Double(x-r+1, y-r+1, (r-1)*2, (r-1)*2) );
            }
        }
//        System.out.println("drawn:");
//        System.out.println("    masses: "+GraphicPanel.drawnMassesCount);
//        System.out.println("    springs: "+GraphicPanel.drawnSpringsCount);
//        System.out.println("    walls: "+GraphicPanel.drawnWallsCount);
//        System.out.println("    bodies: "+GraphicPanel.drawnSpringBodiesCount);
    }

    public void drawEngineMainBound()
    {
        Rectangle2D pros = new Rectangle2D.Double( engineToScrX( scene.getJETContext().getMainBound().getX() ),
                                                   engineToScrY( scene.getJETContext().getMainBound().getMaxY() ),
                                                    scene.getJETContext().getMainBound().getWidth() * viewScale,
                                                    scene.getJETContext().getMainBound().getHeight() *viewScale );
        g2d.setColor(Color.BLACK);
        g2d.draw(pros);
    }
    
    
    public void drawWallCatchArea(Wall wall)
    {
        Vec2d center = wall.getCenter();

        double x = engineToScrX( center.getX() );
        double y = engineToScrY( center.getY() );

        g2d.draw( new Rectangle2D.Double(x-WALL2D_CATCH_AREA_SIZE, y-WALL2D_CATCH_AREA_SIZE,
                                          WALL2D_CATCH_AREA_SIZE*2, WALL2D_CATCH_AREA_SIZE*2) );
    }
    
    public void drawSpringCatchArea(Spring spring)
    {
        Vec2d center = spring.getCenter();

        double x = engineToScrX( center.getX() );
        double y = engineToScrY( center.getY() );

        g2d.draw( new Rectangle2D.Double(x-WALL2D_CATCH_AREA_SIZE, y-WALL2D_CATCH_AREA_SIZE,
                                          WALL2D_CATCH_AREA_SIZE*2, WALL2D_CATCH_AREA_SIZE*2) );
    }

    public void drawRSpringCatchArea(RSpring rs)
    {
        Vec2d center=null;
        for(int i=1; i<=3; i++)
        {
            switch(i) {
                case 1 : center=rs.getA().getMidVec(.5).getAdded(rs.getM2().getPosition()); break;
                case 2 : center=rs.getM2().getPosition(); break;
                case 3 : center=rs.getB().getMidVec(.5).getAdded(rs.getM2().getPosition()); break;
            }

            double x = engineToScrX( center.getX() );
            double y = engineToScrY( center.getY() );

            g2d.draw( new Rectangle2D.Double(x-WALL2D_CATCH_AREA_SIZE, y-WALL2D_CATCH_AREA_SIZE,
                                              WALL2D_CATCH_AREA_SIZE*2, WALL2D_CATCH_AREA_SIZE*2) );
        }
    }

    public void drawSec2d(Sec2d sec)
    {
        double x1 = engineToScrX( sec.getV1().getX() );
        double y1 = engineToScrY( sec.getV1().getY() );
        double x2 = engineToScrX( sec.getV2().getX() );
        double y2 = engineToScrY( sec.getV2().getY() );
        
        g2d.draw( new Line2D.Double(x1, y1, x2, y2) );
    }
    public void drawScreenArrow(Vec2d v1, Vec2d v2, double k)
    {
        Sec2d sec = new Sec2d(v1, v2);
        
        double kat = sec.getAngleY();
        double len = sec.getLength();
        if ( len > 0 )
        {
            Vec2d top = new Vec2d( 0, len );
            Vec2d left = new Vec2d( -3*k, len - 6*k );
            Vec2d right = new Vec2d( 3*k, len - 6*k );
            top.rotate(kat);
            left.rotate(kat);
            right.rotate(kat);

            double x1 =  v1.getX() ;
            double y1 =  v1.getY() ;
            double xTop = v1.getX()+top.getX() ;
            double yTop =  v1.getY()+top.getY() ;
            double xLeft =  v1.getX()+left.getX() ;
            double yLeft =  v1.getY()+left.getY() ;
            double xRight =  v1.getX()+right.getX() ;
            double yRight =  v1.getY()+right.getY() ;

            //g2d.setColor(Color.ORANGE);
            g2d.draw( new Ellipse2D.Double(x1-2*k, y1-2*k, 4*k, 4*k) );

            g2d.draw( new Line2D.Double(x1, y1, xTop, yTop) );
            g2d.draw( new Line2D.Double(xLeft, yLeft, xTop, yTop) );
            g2d.draw( new Line2D.Double(xRight, yRight, xTop, yTop) );
        }
    }
    public void drawEngineArrow(Vec2d v1, Vec2d v2, double k)
    {
        Sec2d sec = new Sec2d(v1, v2);
        
        double kat = sec.getAngleY();
        double len = sec.getLength();
        if ( len > 0 )
        {
            Vec2d top = new Vec2d( 0, len );
            Vec2d left = new Vec2d( -3*k, len - 6*k );
            Vec2d right = new Vec2d( 3*k, len - 6*k );
            top.rotate(kat);
            left.rotate(kat);
            right.rotate(kat);

            double x1 = engineToScrX( v1.getX() );
            double y1 = engineToScrY( v1.getY() );
            double xTop = engineToScrX( v1.getX()+top.getX() );
            double yTop = engineToScrY( v1.getY()+top.getY() );
            double xLeft = engineToScrX( v1.getX()+left.getX() );
            double yLeft = engineToScrY( v1.getY()+left.getY() );
            double xRight = engineToScrX( v1.getX()+right.getX() );
            double yRight = engineToScrY( v1.getY()+right.getY() );

            g2d.draw( new Ellipse2D.Double((x1-2*k),
                                           (y1-2*k),
                                           (4*k),
                                           (4*k)) );

            g2d.draw( new Line2D.Double(x1, y1, xTop, yTop) );
            g2d.draw( new Line2D.Double(xLeft, yLeft, xTop, yTop) );
            g2d.draw( new Line2D.Double(xRight, yRight, xTop, yTop) );
        }
    }
    
    public void drawMouseCatchArea()
    {
        g2d.setColor( MOVE_MANY_MASS2D_RECT2D_COLOR );
        g2d.draw( new Rectangle2D.Double( engineToScrX(scene.EC.engCursor.getX()) - MOVE_MANY_MASS2D_RECT2D_SIZE,
                                          engineToScrY(scene.EC.engCursor.getY()) - MOVE_MANY_MASS2D_RECT2D_SIZE,
                                          MOVE_MANY_MASS2D_RECT2D_SIZE * 2,
                                          MOVE_MANY_MASS2D_RECT2D_SIZE * 2) );
    }
    public void drawEngineRect2d(Rect2d engRect)
    {
        double x1 = engineToScrX( engRect.getX1() );
        double y1 = engineToScrY( engRect.getY1() );
        double x2 = engineToScrX( engRect.getX2() );
        double y2 = engineToScrY( engRect.getY2() );

        g2d.draw( new Rectangle2D.Double( x1, y1, x2-x1, y2-y1 ) );
        System.out.println("x1= "+x1+" y1= "+y1+" x2= "+x2+" y2= "+y2 );
    }
    public void drawAddWall2dLine()
    {
        Mass mass = (Mass)CC.MC.mouseObject1;
        
        double x1 = engineToScrX( mass.getPosition().getX() );
        double y1 = engineToScrY( mass.getPosition().getY() );
        double x2 = scene.EC.scrCursor.getX();
        double y2 = scene.EC.scrCursor.getY();
        g2d.setColor( ADD_SINGLE_WALL2D_LINE_COLOR );
        g2d.draw( new Line2D.Double(x1, y1, x2, y2) );
    }
    public void drawAddSpring2dLine()
    {
        double x1=0, x2=0, y1=0, y2=0;
        if (CC.MC.mouseObject1 instanceof Mass)
        {
            Mass mass = (Mass)CC.MC.mouseObject1;

            x1 = engineToScrX( mass.getPosition().getX() );
            y1 = engineToScrY( mass.getPosition().getY() );
            x2 = scene.EC.scrCursor.getX();
            y2 = scene.EC.scrCursor.getY();
        }
        else if (CC.MC.mouseObject1 instanceof RigidBody)
        {
            x1 = engineToScrX( CC.MC.mouseVec.getX() );
            y1 = engineToScrY( CC.MC.mouseVec.getY() );
            x2 = scene.EC.scrCursor.getX();
            y2 = scene.EC.scrCursor.getY();
        }

        g2d.setColor( ADD_SINGLE_SPRING2D_LINE_COLOR );
        g2d.draw( new Line2D.Double(x1, y1, x2, y2) );
    }

    private void drawAddRSpring1()
    {
        Mass mass =(Mass)CC.MC.mouseObject1;
        double x1 = engineToScrX( mass.getPosition().getX() );
        double y1 = engineToScrY( mass.getPosition().getY() );
        double x2 = scene.EC.scrCursor.getX();
        double y2 = scene.EC.scrCursor.getY();
        g2d.setColor( ADD_SINGLE_RSPRING_LINE_A_COLOR );
        drawScreenArrow(new Vec2d(x2,y2), new Vec2d(x1,y1), 1);
    }
    private void drawAddRSpring2()
    {
        Mass mass =(Mass)CC.MC.mouseObject1;
        Mass mass2 =(Mass)CC.MC.mouseObject2;
        double x1 = engineToScrX( mass.getPosition().getX() );
        double y1 = engineToScrY( mass.getPosition().getY() );
        double x2 = engineToScrX( mass2.getPosition().getX() );
        double y2 = engineToScrY( mass2.getPosition().getY() );
        double x3 = scene.EC.scrCursor.getX();
        double y3 = scene.EC.scrCursor.getY();
        g2d.setColor( ADD_SINGLE_RSPRING_LINE_A_COLOR );
        drawScreenArrow(new Vec2d(x2,y2), new Vec2d(x1,y1), 1);
        g2d.setColor( ADD_SINGLE_RSPRING_LINE_B_COLOR );
        drawScreenArrow(new Vec2d(x2,y2), new Vec2d(x3,y3), 1);

        int r = 15;
        int ax = (int)x2-r;
        int ay = (int)y2-r;
        Vec2d a = new Vec2d(x1-x2,y1-y2);
        Vec2d b = new Vec2d(x3-x2,y3-y2);
        int da = (int)(Math.toDegrees(a.getAngleX())*-1 + 360);
        int db = (int)(Math.toDegrees(b.getAngleX())*-1 + 360);
        int dist = db-da;
        g2d.setColor(ADD_SINGLE_RSPRING_ARC_COLOR);
        g2d.drawArc(ax,ay,r*2,r*2,da,dist);
    }
    
    public void drawCreateCircle()
    {
        Vec2d vec = engineToScrVec(CC.MC.mouseVec);
        vec.sub( scene.EC.scrCursor );

        double x = engineToScrX( CC.MC.mouseVec.getX() );
        double y = engineToScrY( CC.MC.mouseVec.getY() );
        double r = vec.getMagnitude();
        
        g2d.setColor( Color.GRAY );
        g2d.draw( new Ellipse2D.Double( x-r, y-r, 2*r, 2*r) );

        double dAngle = Math.PI*2 / CC.MC.mouseInteger;
        for( int i=0; i<CC.MC.mouseInteger; i++ )
        {
            Vec2d pos = vec.getRotated(dAngle * i +Math.PI);
            x = engineToScrX( CC.MC.mouseVec.getX() ) + pos.getX();
            y = engineToScrY( CC.MC.mouseVec.getY() ) + pos.getY();
            r = 1;
            g2d.setColor( Color.RED );
            g2d.draw( new Ellipse2D.Double( x-r, y-r, 2*r, 2*r) );
        }
        g2d.drawString("[ "+CC.MC.mouseInteger+" ]",(float)CC.MC.mouseEvent.getX(),(float)CC.MC.mouseEvent.getY());
    }
    
    public void drawCreateSquareNet()
    {
        Vec2d v1 = engineToScrVec(CC.MC.mouseVec); //new Vec2d( CC.MC.mouseVec );
        Vec2d v2 = engineToScrVec(CC.MC.mouseVec2); //new Vec2d( CC.MC.mouseVec2 );

        int dim = CC.MC.mouseInteger ;
        double cellWidth = (v2.getX() - v1.getX()) / (double)(dim);
        double cellHeight = (v2.getY() - v1.getY()) / (double)(dim);
        double radius = 1;

        for( int r = 0; r<=dim; r++)
        {
            g2d.setColor( Color.LIGHT_GRAY );
            g2d.draw( new Line2D.Double(v1.getX(), v1.getY() + cellHeight*r, v2.getX(), v1.getY() + cellHeight*r) );
            for( int c = 0; c<=dim; c++)
            {
                if ( r == 0 ){
                    g2d.setColor( Color.LIGHT_GRAY );
                    g2d.draw( new Line2D.Double(v1.getX() + cellWidth*c, v1.getY(), v1.getX()+ cellWidth*c, v2.getY()) );
                }

                double x = v1.getX() + cellWidth * r;
                double y = v1.getY() + cellHeight * c;
                g2d.setColor(Color.RED);
                g2d.draw( new Ellipse2D.Double( x-radius, y-radius, 2*radius, 2*radius) );
            }
        }
        g2d.drawString("[ "+CC.MC.mouseInteger+" ]",(float)CC.MC.mouseEvent.getX(),(float)CC.MC.mouseEvent.getY());
    }
    public void drawMainGrid()
    {
        JScrollPane sPane = MyGuiHelper.getFirstScrollPaneAncestor(this);
        
        if ( sPane != null )
        {
            Rectangle vRect = getVisibleRect();

            int viewPosX = (int)sPane.getViewport().getViewPosition().getX();
            int viewPosY = (int)sPane.getViewport().getViewPosition().getY();

            if ( scene.GC.isDrawHelpGrid() )
                g2d.setColor( mainGridColor );
            else
                g2d.setColor( helpGridColor );

            double endX = scene.getJETContext().getMainBound().getWidth();
            double endY = scene.getJETContext().getMainBound().getHeight();

            // pion
            int count=0;
            double ymin =  engineToScrY( scene.getJETContext().getMainBound().getMaxY() );
            double ymax = ymin + scene.getJETContext().getMainBound().getHeight() *viewScale;

            for(double i = 0; i<=endX; i += mainGriddX)
            {
                double lineX = engineToScrX(i);
                if (lineX>=vRect.getMinX() && lineX<=vRect.getMaxX())
                {
                    g2d.draw( new Line2D.Double(lineX,
                                                ymin,
                                                lineX,
                                                ymax
                                               ) );
                    if (scene.GC.isDrawMainGridXNumbers())
                        g2d.drawString(""+(int)(count*mainGriddX), (int)lineX, 15+viewPosY);
                }
                count++;
            }
            // poziom
            count=0;
            double lineX1 = ltvpdX+1;
            double lineX2 = engineToScrX(endX);
            for(double i = 0; i<=endY; i += mainGriddY)
            {
                double lineY = engineToScrY(i);
                if (lineY>=vRect.getMinY() && lineY<=vRect.getMaxY())
                {
                    g2d.draw( new Line2D.Double(lineX1,
                                                lineY,
                                                lineX2,
                                                lineY)
                                                );
                    if (scene.GC.isDrawMainGridYNumbers())
                        g2d.drawString(""+(int)(count*mainGriddY), viewPosX, (int)lineY);
                }
                count++;
            }
        }
    }
    public void drawHelpGrid()
    {
        g2d.setColor( helpGridColor );
        //JScrollPane sPane = scene.GC.getGraphicPanelScrollPane();
        JScrollPane sPane = MyGuiHelper.getFirstScrollPaneAncestor(this);
        if ( sPane != null )
        {
            int viewPosX = (int)sPane.getViewport().getViewPosition().getX();
            int viewPosY = (int)sPane.getViewport().getViewPosition().getY();

            double endX = scene.getJETContext().getMainBound().getWidth();
            double endY = scene.getJETContext().getMainBound().getHeight();

            Rectangle vRect = getVisibleRect();
            // pion
            int count=0;
            double lineY1 = ltvpdY+1;
            double lineY2 = this.getHeight()-engineToScrY(endY)-1 ;
            for(double i = 0; i<=endX; i += helpGriddX)
            {
                double lineX = engineToScrX(i);
                if (lineX>=vRect.getMinX() && lineX<=vRect.getMaxX())
                {
                    g2d.draw( new Line2D.Double(lineX,
                                                ltvpdY+1,
                                                lineX,
                                                lineY2) );
                    if (scene.GC.isDrawHelpGridXNumbers())
                        g2d.drawString(""+(int)(count*helpGriddX), (int)lineX, 15+viewPosY);
                }
                count++;
            }

            // poziom
            count=0;
            double lineX1 = ltvpdX+1;
            double lineX2 = engineToScrX(endX);
            for(double i = 0; i<=endY; i += helpGriddY)
            {
                double lineY = engineToScrY(i);
                if (lineY>=vRect.getMinY() && lineY<=vRect.getMaxY())
                {
                    g2d.draw( new Line2D.Double(lineX1,
                                                lineY,
                                                lineX2,
                                                lineY)
                                                );
                    if (scene.GC.isDrawHelpGridYNumbers())
                        g2d.drawString(""+(int)(count*helpGriddY), viewPosX, (int)lineY);
                }
                count++;
            }
        }
    }
    public void drawSpringBodyMass( SpringBody sb, Mass mass2d)
    {
        // aktualne polozenie masy
        double x = engineToScrX( mass2d.getPosition().getX() );
        double y = engineToScrY( mass2d.getPosition().getY() );
        double r = (mass2d.getMass()/2.) * viewScale;


//        Rectangle vRect = getVisibleRect();
//        if (vRect.contains(x, y))
//        {
            //System.out.println("vRect.contains");
            // kolko
            if ( mass2d.isMoveable() )
            {
                g2d.setPaint(Color.BLACK);
                g2d.draw( new Ellipse2D.Double(x-r, y-r, r*2, r*2) );
                g2d.fill( new Ellipse2D.Double(x-r, y-r, r*2, r*2) );
            }
            else
            {
                g2d.setColor( Color.GRAY );
                g2d.draw( new Line2D.Double(x-3,y-3,x+3,y+3) );
                g2d.draw( new Line2D.Double(x-3,y+3,x+3,y-3) );
                g2d.setPaint(Color.RED);
                g2d.draw( new Ellipse2D.Double(x-(r+1), y-(r+1), (r+1)*2, (r+1)*2) );
            }

            if ( mass2d.hasMoved() && scene.GC.isDrawMass2dIfMoved() )
            {
                g2d.setPaint(Color.RED);
                double rad = (r+6)*viewScale;
                g2d.draw( new Ellipse2D.Double(x-rad, y-rad, rad*2, rad*2) );
            }

            // predkosc
            if ( scene.GC.isDrawMass2dVelocities() )
            {
                g2d.setColor(Color.green);
                Vec2d tmp = new Vec2d( mass2d.getPosition() );
                Vec2d tmp2 = new Vec2d( mass2d.getVelocity() );
                tmp.add( tmp2 );
                double k = mass2d.getVelocity().getMagnitude()/50;
                drawEngineArrow( mass2d.getPosition(),  tmp,  k);
            }

            // Sila
            if ( scene.GC.isDrawMass2dForces() )
            {
                g2d.setColor(Color.red);
                Vec2d tmp = new Vec2d( mass2d.getPosition() );
                Vec2d tmp2 = new Vec2d( mass2d.getForce().getScaled(0.5) );
                tmp.add( tmp2 );
                double k = mass2d.getForce().getMagnitude()/100;
                drawEngineArrow( mass2d.getPosition(),  tmp,  k);
            }

            // numer
            if ( scene.GC.isDrawMassesNumbers() )
            {
                g2d.setColor( Color.BLACK );
                g2d.drawString(""+sb.getMassList().indexOf(mass2d), (int)x, (int)y);
            }
            SwingGraphicPanel.drawnMassesCount++;
//        }
        
    }
    public void drawSpringBodyWall( SpringBody sb, Wall wall2d )
    {
        double x1 = engineToScrX( wall2d.getM1().getPosition().getX() );
        double y1 = engineToScrY( wall2d.getM1().getPosition().getY() );
        double x2 = engineToScrX( wall2d.getM2().getPosition().getX() );
        double y2 = engineToScrY( wall2d.getM2().getPosition().getY() );

        //if (getVisibleRect().contains(x1,y1) || getVisibleRect().contains(x2,y2))
        //{
            if ( sb.getBorder().isProperlyBuilt() )
                g2d.setColor( SPRINGBODY_BORDER_COLOR );
            else
                g2d.setColor( SPRINGBODY_WALL2D_COLOR );

            g2d.draw( new Line2D.Double(x1, y1, x2, y2) );
            //GraphicHelper.drawArrow(g2d, x1, y1, x2, y2, 2);

            if ( scene.GC.isDrawWallsNumbers() )
                g2d.drawString(""+sb.getBorder().getWallList().indexOf(wall2d), (int)(x1+(x2-x1)/2), 10+(int)(y1+(y2-y1)/2) );

            if ( CC.MC.getMouseMode() == MouseMode.ADD_SINGLE_WALL )
            {
                g2d.setColor( WALL2D_CATCH_AREA_COLOR );
                drawWallCatchArea(wall2d);
            }
            SwingGraphicPanel.drawnWallsCount++;
        //}
    }

    public void drawSpringBodySpring(SpringBody sb, Spring spring)
    {
        if (spring.isAlive()) {
            double x1 = engineToScrX( spring.getM1().getPosition().getX() );
            double y1 = engineToScrY( spring.getM1().getPosition().getY() );
            double x2 = engineToScrX( spring.getM2().getPosition().getX() );
            double y2 = engineToScrY( spring.getM2().getPosition().getY() );

            //if (getVisibleRect().contains(x1,y1) || getVisibleRect().contains(x2,y2))
            //{
                g2d.setColor( SPRINGBODY_SPRING_COLOR );
                g2d.draw( new Line2D.Double(x1, y1, x2, y2) );
                if ( scene.GC.isDrawSpringsNumbers() )
                    g2d.drawString(""+sb.getSpringList().indexOf(spring), (int)(x1+(x2-x1)/2), (int)(y1+(y2-y1)/2) );

                if ( CC.MC.getMouseMode() == MouseMode.ADD_SINGLE_SPRING )
                {
                    g2d.setColor( SPRING2D_CATCH_AREA_COLOR );
                    drawSpringCatchArea(spring);
                }
                SwingGraphicPanel.drawnSpringsCount++;
            //}
        }
    }

    public void drawSpringBodyRSpring(SpringBody sb, RSpring rSpring)
    {
        double x1 = engineToScrX( rSpring.getM1().getPosition().getX() );
        double y1 = engineToScrY( rSpring.getM1().getPosition().getY() );
        double x2 = engineToScrX( rSpring.getM2().getPosition().getX() );
        double y2 = engineToScrY( rSpring.getM2().getPosition().getY() );
        double x3 = engineToScrX( rSpring.getM3().getPosition().getX() );
        double y3 = engineToScrY( rSpring.getM3().getPosition().getY() );

        g2d.setColor( SPRINGBODY_RSPRING_COLOR );
        drawScreenArrow(new Vec2d(x2,y2), new Vec2d(x1,y1), 1);
        drawScreenArrow(new Vec2d(x2,y2), new Vec2d(x3,y3), 1);

        int r = (int)(RSPRING_ARC_RADIUS*viewScale);
        int ax = (int)x2-r;
        int ay = (int)y2-r;
        Vec2d a = new Vec2d(x1-x2,y1-y2);
        Vec2d b = new Vec2d(x3-x2,y3-y2);
        int da = (int)(Math.toDegrees(a.getAngleX())*-1 + 360);
        int db = (int)(Math.toDegrees(b.getAngleX())*-1 + 360);
        int dist = db-da;
        g2d.setColor(SPRINGBODY_RSPRING_ARC_COLOR);
        g2d.drawArc(ax,ay,r*2,r*2,da,dist);

        if ( CC.MC.getMouseMode() == MouseMode.ADD_SINGLE_RSPRING )
        {
            g2d.setColor( RSPRING_CATCH_AREA_COLOR );
            drawRSpringCatchArea(rSpring);
        }
    }
    
    public void drawSpringBodyFace(Face f) {
        if (f.isVisible()) {
            int count = f.getPointsCount();
            double[] xd = f.getXPoints();
            double[] yd = f.getYPoints();

            int[] x = new int[count];
            int[] y = new int[count];

            for(int i=0; i<count; i++) {
                x[i] = (int)engineToScrX(xd[i]);
                y[i] = (int)engineToScrY(yd[i]);
            }

            g2d.setColor(f.getColor());
            g2d.fillPolygon(x, y, count);
        }
    }

    public void drawEngineSpring( Spring spring )
    {
        if (spring.isAlive()) {
            double x1 = engineToScrX( spring.getM1().getPosition().getX() );
            double y1 = engineToScrY( spring.getM1().getPosition().getY() );
            double x2 = engineToScrX( spring.getM2().getPosition().getX() );
            double y2 = engineToScrY( spring.getM2().getPosition().getY() );

            //if (getVisibleRect().contains(x1,y1) || getVisibleRect().contains(x2,y2))
            //{
                g2d.setColor( ENGINE_SPRING_COLOR );
                g2d.draw( new Line2D.Double(x1, y1, x2, y2) );

                if ( CC.MC.getMouseMode() == MouseMode.ADD_SINGLE_SPRING )
                {
                    g2d.setColor( SPRING2D_CATCH_AREA_COLOR );
                    drawSpringCatchArea(spring);
                }
            //}
        }
    }

    public void drawEngineRSpring(RSpring rSpring)
    {
        double x1 = engineToScrX( rSpring.getM1().getPosition().getX() );
        double y1 = engineToScrY( rSpring.getM1().getPosition().getY() );
        double x2 = engineToScrX( rSpring.getM2().getPosition().getX() );
        double y2 = engineToScrY( rSpring.getM2().getPosition().getY() );
        double x3 = engineToScrX( rSpring.getM3().getPosition().getX() );
        double y3 = engineToScrY( rSpring.getM3().getPosition().getY() );

        g2d.setColor( ENGINE_RSPRING_COLOR );
        drawScreenArrow(new Vec2d(x2,y2), new Vec2d(x1,y1), 1);
        drawScreenArrow(new Vec2d(x2,y2), new Vec2d(x3,y3), 1);

        int r = (int)(RSPRING_ARC_RADIUS*viewScale);
        int ax = (int)x2-r;
        int ay = (int)y2-r;
        Vec2d a = new Vec2d(x1-x2,y1-y2);
        Vec2d b = new Vec2d(x3-x2,y3-y2);
        int da = (int)(Math.toDegrees(a.getAngleX())*-1 + 360);
        int db = (int)(Math.toDegrees(b.getAngleX())*-1 + 360);
        int dist = db-da;
        g2d.setColor(ENGINE_RSPRING_ARC_COLOR);
        g2d.drawArc(ax,ay,r*2,r*2,da,dist);

        if ( CC.MC.getMouseMode() == MouseMode.ADD_SINGLE_RSPRING )
        {
            g2d.setColor( RSPRING_CATCH_AREA_COLOR );
            drawRSpringCatchArea(rSpring);
        }
    }

    public void drawBoundingArea(BoundingArea ba)
    {
        if (ba instanceof BoundingBox)
        {
            BoundingBox bb = (BoundingBox)ba;
            
            double x1 = engineToScrX( bb.getMinX() );
            double y1 = engineToScrY( bb.getMaxY() );
            double width =  bb.getWidth() * viewScale;
            double height =  bb.getHeight() * viewScale ;

            g2d.draw( new Rectangle2D.Double(x1, y1, width, height) );
        }
    }
    
    public void drawSpringBody(SpringBody sb)
    {
        Rectangle vRect = getVisibleRect();
        BoundingArea ba = sb.getBoundingArea();

        // boundingBox
        if ( scene.GC.isDrawBoundingBoxes() ) {
            g2d.setColor(SPRINGBODY_BOUNINGBOX_COLOR);
            drawBoundingArea( sb.getBoundingArea() );
        }

        // Faces
        Collection<Face> faceCol = sb.getFaceListSync();
        synchronized(faceCol) {
            for(Face f : faceCol)
                drawSpringBodyFace(f);
        }

        // Shape Matching Stuff
        if (sb.isMatchShape() && scene.GC.isDrawMasses2d()) {
            Collection<Mass> massCol = Collections.synchronizedList(sb.rb.dynVecList);
            synchronized(massCol) {
                for(Mass m : massCol) {
                    double tets = 0;
                    double x = engineToScrX( m.getPosition().getX() );
                    double y = engineToScrY( m.getPosition().getY() );
                    double r = (m.getMass()/3.) * viewScale;
                    g2d.setPaint(Color.BLUE);
                    g2d.draw( new Ellipse2D.Double(x-r, y-r, r*2, r*2) );
                    g2d.fill( new Ellipse2D.Double(x-r, y-r, r*2, r*2) );
                }
            }
        }

        // sprezyny
        if ( scene.GC.isDrawSprings2d() ) {
            Collection<Spring> springCol = sb.getSpringListSync();

            synchronized(springCol) {
                for(Spring spring : springCol)
                    drawSpringBodySpring(sb, spring);
            }
        }

        // sprezyny rotujace
        if ( scene.GC.isDrawSprings2d() ) {
            Collection<RSpring> rSpringCol = sb.getRSpringListSync();

            synchronized(rSpringCol) {
                for(RSpring rSpring : rSpringCol)
                    drawSpringBodyRSpring(sb, rSpring);
            }
        }

        // sciany brzegu
        if( scene.GC.isDrawWalls2d() ) {
            Collection<Wall> wallCol = sb.getBorder().getWallListSync();

            synchronized (wallCol) {
                for(Wall wall : wallCol)
                    drawSpringBodyWall(sb, wall);
            }

            if( sb.getBorder().getWallsCount()>0)
                if (scene.GC.isDrawBorderOrientation())
                    if ( sb.getBorder().isCounterClockwise() )
                    {
                        g2d.setColor(Color.BLUE);
                        g2d.drawString("is CCW",-10+(int)engineToScrX( sb.getBorder().getWall(0).getCenter().getX() ),
                                                -10+(int)engineToScrY( sb.getBorder().getWall(0).getCenter().getY() ) );
                    }
                    else
                    {
                        g2d.setColor(Color.BLACK);
                        g2d.drawString("is CW",-6+(int)engineToScrX( sb.getBorder().getWall(0).getCenter().getX() ),
                                              -10+(int)engineToScrY( sb.getBorder().getWall(0).getCenter().getY() ) );
                    }
        }

        // masy
        if ( scene.GC.isDrawMasses2d() ) {
            Collection<Mass> massCol = sb.getMassListSync();
            synchronized(massCol) {
                for(Mass mass : massCol)
                    drawSpringBodyMass(sb, mass);
            }
        }

        // srodek geometryczny
        if ( scene.GC.isDrawSpringBodyGeomCenter() )
        {
            Vec2d center = sb.getCenterVec();
            g2d.setColor(Color.ORANGE);
            double x = engineToScrX( center.getX() );
            double y = engineToScrY( center.getY() );
            double f = Math.sqrt( sb.getBoundingArea().getWidth()*sb.getBoundingArea().getHeight() );
            double r = 3* (f/100.) * viewScale;

            g2d.draw( new Ellipse2D.Double(x-r, y-r, r*2, r*2) );
        }
        SwingGraphicPanel.drawnSpringBodiesCount++;
        
    }
    
    public void drawSpringBodyWalabersCollisions()
    {
        if (CC.isSceneAnimated(scene.getName()))
        {
            JETContext ctx = CC.getSceneAnimator(scene.getName()).context;
            for(int i=0; i<ctx.sbColInfoCount; i++)
            {
                SBCollision col = ctx.sbColInfoList.get(i);
                SpringBody sb1 = (SpringBody) col.body1;

                g2d.setColor(Color.BLACK);
                drawEngineArrow( col.bodyApm.getPosition(), col.hitPt, 1 );

//                Vec2d massNormPt = new Vec2d( sb1.getBorder().getMassNormal(col.bodyApm).getScaled(25.) );
//                massNormPt.add( col.bodyApm.getPosition() );
//
//                g2d.setColor(Color.CYAN);
//                drawEngineArrow( col.bodyApm.getPosition(), massNormPt, 1);

                Vec2d wallCenter = new Vec2d(col.bodyBwall.getCenter());
                Vec2d ptByNorm = new Vec2d(col.hitPt);
                ptByNorm.add(col.norm.getScaled(50.));
                g2d.setColor(Color.ORANGE);
                drawEngineArrow( col.hitPt, ptByNorm, 1);
            }

            double s = 10;
            for(int i=0; i<ctx.vAList.size(); i++) {
                g2d.setColor(Color.GREEN);
                drawEngineArrow( ctx.hpList.get(i), ctx.hpList.get(i).getAdded(ctx.vAList.get(i).getScaled(s)), 1);
                g2d.setColor(Color.RED);
                drawEngineArrow( ctx.hpList.get(i), ctx.hpList.get(i).getAdded(ctx.vBList.get(i).getScaled(s)), 1);
                g2d.setColor(Color.PINK);
                drawEngineArrow( ctx.hpList.get(i), ctx.hpList.get(i).getAdded(ctx.vABList.get(i).getScaled(s)), 1);
            }
        }
    }

    public void drawRigidBodyWalabersCollisions()
    {
        if (CC.isSceneAnimated(scene.getName()))
        {
            JETContext ctx = CC.getSceneAnimator(scene.getName()).context;
            for(int i=0; i<ctx.rbColInfoCount; i++) {
                SBCollision col = ctx.rbColInfoList.get(i);

                g2d.setColor(Color.BLACK);
                drawEngineArrow( col.bodyApm.getPosition(), col.hitPt, 1 );

                Vec2d massNormPt = new Vec2d( col.body1.getBorder().getMassNormal(col.bodyApm).getScaled(1.) );
                massNormPt.add( col.bodyApm.getPosition() );

                g2d.setColor(Color.CYAN);
                drawEngineArrow( col.bodyApm.getPosition(), massNormPt, 1);

                Vec2d wallCenter = new Vec2d(col.bodyBwall.getCenter());
                Vec2d ptByNorm = new Vec2d(col.hitPt);
                ptByNorm.add(col.norm.getScaled(50.));
                g2d.setColor(Color.ORANGE);
                drawEngineArrow( col.hitPt, ptByNorm, 1);

                g2d.setColor(Color.PINK);
                drawEngineArrow( col.hitPt, col.hitPt.getAdded(col.vAB.getScaled(50)), 1);
            }
        }
    }

    public void drawSelectionRect() {
        if (scene.EC.selectionRect != null)
        {
            double x1 = engineToScrX( scene.EC.selectionRect.getX1() );
            double y1 = engineToScrY( scene.EC.selectionRect.getY1() );
            double x2 = engineToScrX( scene.EC.selectionRect.getX2() );
            double y2 = engineToScrY( scene.EC.selectionRect.getY2() );

            g2d.setColor(Color.GREEN);
            g2d.draw( new Line2D.Double(x1,y1, x1,y2) );
            g2d.draw( new Line2D.Double(x2,y1, x2,y2) );
            g2d.draw( new Line2D.Double(x1,y1, x2,y1) );
            g2d.draw( new Line2D.Double(x1,y2, x2,y2) );
        }
    }

    public void drawSelectionInOrder()
    {
        if (scene.EC.vecList.size()>1)  {
            for(int i=0; i<scene.EC.vecList.size()-1; i++) {
                double x1 = engineToScrX( scene.EC.vecList.get(i).x );
                double y1 = engineToScrY( scene.EC.vecList.get(i).y );
                double x2 = engineToScrX( scene.EC.vecList.get(i+1).x );
                double y2 = engineToScrY( scene.EC.vecList.get(i+1).y );

                g2d.setColor(Color.pink);
                g2d.draw( new Line2D.Double(x1,y1, x2,y2) );
            }
        }
    }

    public void drawSelectionGroup()
    {
        g2d.setPaint(Color.YELLOW);
        Collection<Mass> massCol = scene.EC.selectionGroup.getMassListSync();
        synchronized(massCol) {
            for (Mass mass : massCol)
            {
                // aktualne polozenie masy
                double x = engineToScrX( mass.getPosition().getX() );
                double y = engineToScrY( mass.getPosition().getY() );
                double r = mass.getMass() *viewScale;

                g2d.draw( new Ellipse2D.Double(x-r, y-r, r*2, r*2) );
                g2d.fill( new Ellipse2D.Double(x-r, y-r, r*2, r*2) );
            }
        }

        Collection<Spring> springCol = scene.EC.selectionGroup.getSpringListSync();
        synchronized(springCol) {
            for (Spring spring : springCol)
            {
                double x1 = engineToScrX( spring.getM1().getPosition().getX() );
                double y1 = engineToScrY( spring.getM1().getPosition().getY() );
                double x2 = engineToScrX( spring.getM2().getPosition().getX() );
                double y2 = engineToScrY( spring.getM2().getPosition().getY() );

                g2d.draw( new Line2D.Double(x1, y1, x2, y2) );

                g2d.draw( new Line2D.Double(x1, y1-1, x2, y2-1) );
                g2d.draw( new Line2D.Double(x1, y1+1, x2, y2+1) );

                g2d.draw( new Line2D.Double(x1-1, y1, x2-1, y2) );
                g2d.draw( new Line2D.Double(x1+1, y1, x2+1, y2) );
            }
        }

        Collection<RSpring> rSpringCol = scene.EC.selectionGroup.getRSpringListSync();
        synchronized(rSpringCol) {
            for (RSpring rSpring : rSpringCol)
            {
                double x1 = engineToScrX( rSpring.getM1().getPosition().getX() );
                double y1 = engineToScrY( rSpring.getM1().getPosition().getY() );
                double x2 = engineToScrX( rSpring.getM2().getPosition().getX() );
                double y2 = engineToScrY( rSpring.getM2().getPosition().getY() );
                double x3 = engineToScrX( rSpring.getM3().getPosition().getX() );
                double y3 = engineToScrY( rSpring.getM3().getPosition().getY() );

                drawScreenArrow(new Vec2d(x2,y2), new Vec2d(x1,y1), 1);

                drawScreenArrow(new Vec2d(x2+1,y2), new Vec2d(x1+1,y1), 1);
                drawScreenArrow(new Vec2d(x2-1,y2), new Vec2d(x1-1,y1), 1);
                drawScreenArrow(new Vec2d(x2,y2+1), new Vec2d(x1,y1+1), 1);
                drawScreenArrow(new Vec2d(x2,y2-1), new Vec2d(x1,y1-1), 1);

                drawScreenArrow(new Vec2d(x2,y2), new Vec2d(x3,y3), 1);

                drawScreenArrow(new Vec2d(x2+1,y2), new Vec2d(x3+1,y3), 1);
                drawScreenArrow(new Vec2d(x2,y2+1), new Vec2d(x3,y3+1), 1);
                drawScreenArrow(new Vec2d(x2-1,y2), new Vec2d(x3-1,y3), 1);
                drawScreenArrow(new Vec2d(x2,y2-1), new Vec2d(x3,y3-1), 1);

                int r = (int)(RSPRING_ARC_RADIUS*viewScale);
                int ax = (int)x2-r;
                int ay = (int)y2-r;
                Vec2d a = new Vec2d(x1-x2,y1-y2);
                Vec2d b = new Vec2d(x3-x2,y3-y2);
                int da = (int)(Math.toDegrees(a.getAngleX())*-1 + 360);
                int db = (int)(Math.toDegrees(b.getAngleX())*-1 + 360);
                int dist = db-da;
                g2d.drawArc(ax,ay,r*2,r*2,da,dist);

                g2d.drawArc(ax+1,ay,r*2,r*2,da,dist);
                g2d.drawArc(ax,ay+1,r*2,r*2,da,dist);
                g2d.drawArc(ax-1,ay,r*2,r*2,da,dist);
                g2d.drawArc(ax,ay-1,r*2,r*2,da,dist);
            }
        }
        
        Collection<Wall> wallCol = scene.EC.selectionGroup.getWallListSync();
        synchronized(wallCol) {
            for (Wall wall : wallCol)
            {
                double x1 = engineToScrX( wall.getM1().getPosition().getX() );
                double y1 = engineToScrY( wall.getM1().getPosition().getY() );
                double x2 = engineToScrX( wall.getM2().getPosition().getX() );
                double y2 = engineToScrY( wall.getM2().getPosition().getY() );

                g2d.draw( new Line2D.Double(x1, y1, x2, y2) );

                g2d.draw( new Line2D.Double(x1, y1-1, x2, y2-1) );
                g2d.draw( new Line2D.Double(x1, y1+1, x2, y2+1) );

                g2d.draw( new Line2D.Double(x1-1, y1, x2-1, y2) );
                g2d.draw( new Line2D.Double(x1+1, y1, x2+1, y2) );
            }
        }
    }
    
    public void drawTempSelectionGroup()
    {
        g2d.setPaint(Color.ORANGE);
        Collection<Mass> massCol = scene.EC.tempSelectGroup.getMassListSync();
        synchronized(massCol) {
            for (Mass mass : massCol)
            {
                // aktualne polozenie masy
                double x = engineToScrX( mass.getPosition().getX() );
                double y = engineToScrY( mass.getPosition().getY() );
                double r = mass.getMass() *viewScale;

                g2d.draw( new Ellipse2D.Double(x-r, y-r, r*2, r*2) );
                g2d.fill( new Ellipse2D.Double(x-r, y-r, r*2, r*2) );
            }
        }

        Collection<Spring> springCol = scene.EC.tempSelectGroup.getSpringListSync();
        synchronized(springCol) {
            for (Spring spring : springCol)
            {
                double x1 = engineToScrX( spring.getM1().getPosition().getX() );
                double y1 = engineToScrY( spring.getM1().getPosition().getY() );
                double x2 = engineToScrX( spring.getM2().getPosition().getX() );
                double y2 = engineToScrY( spring.getM2().getPosition().getY() );

                g2d.draw( new Line2D.Double(x1, y1, x2, y2) );

                g2d.draw( new Line2D.Double(x1, y1-1, x2, y2-1) );
                g2d.draw( new Line2D.Double(x1, y1+1, x2, y2+1) );

                g2d.draw( new Line2D.Double(x1-1, y1, x2-1, y2) );
                g2d.draw( new Line2D.Double(x1+1, y1, x2+1, y2) );
            }
        }

        Collection<RSpring> rSpringCol = scene.EC.tempSelectGroup.getRSpringListSync();
        synchronized(rSpringCol) {
            for (RSpring rSpring : rSpringCol)
            {
                double x1 = engineToScrX( rSpring.getM1().getPosition().getX() );
                double y1 = engineToScrY( rSpring.getM1().getPosition().getY() );
                double x2 = engineToScrX( rSpring.getM2().getPosition().getX() );
                double y2 = engineToScrY( rSpring.getM2().getPosition().getY() );
                double x3 = engineToScrX( rSpring.getM3().getPosition().getX() );
                double y3 = engineToScrY( rSpring.getM3().getPosition().getY() );

                drawScreenArrow(new Vec2d(x2,y2), new Vec2d(x1,y1), 1);

                drawScreenArrow(new Vec2d(x2+1,y2), new Vec2d(x1+1,y1), 1);
                drawScreenArrow(new Vec2d(x2-1,y2), new Vec2d(x1-1,y1), 1);
                drawScreenArrow(new Vec2d(x2,y2+1), new Vec2d(x1,y1+1), 1);
                drawScreenArrow(new Vec2d(x2,y2-1), new Vec2d(x1,y1-1), 1);

                drawScreenArrow(new Vec2d(x2,y2), new Vec2d(x3,y3), 1);

                drawScreenArrow(new Vec2d(x2+1,y2), new Vec2d(x3+1,y3), 1);
                drawScreenArrow(new Vec2d(x2,y2+1), new Vec2d(x3,y3+1), 1);
                drawScreenArrow(new Vec2d(x2-1,y2), new Vec2d(x3-1,y3), 1);
                drawScreenArrow(new Vec2d(x2,y2-1), new Vec2d(x3,y3-1), 1);

                int r = (int)(RSPRING_ARC_RADIUS*viewScale);
                int ax = (int)x2-r;
                int ay = (int)y2-r;
                Vec2d a = new Vec2d(x1-x2,y1-y2);
                Vec2d b = new Vec2d(x3-x2,y3-y2);
                int da = (int)(Math.toDegrees(a.getAngleX())*-1 + 360);
                int db = (int)(Math.toDegrees(b.getAngleX())*-1 + 360);
                int dist = db-da;
                g2d.drawArc(ax,ay,r*2,r*2,da,dist);

                g2d.drawArc(ax+1,ay,r*2,r*2,da,dist);
                g2d.drawArc(ax,ay+1,r*2,r*2,da,dist);
                g2d.drawArc(ax-1,ay,r*2,r*2,da,dist);
                g2d.drawArc(ax,ay-1,r*2,r*2,da,dist);
            }
        }
        Collection<Wall> wallCol = scene.EC.tempSelectGroup.getWallListSync();
        synchronized(wallCol) {
            for (Wall wall : wallCol)
            {
                double x1 = engineToScrX( wall.getM1().getPosition().getX() );
                double y1 = engineToScrY( wall.getM1().getPosition().getY() );
                double x2 = engineToScrX( wall.getM2().getPosition().getX() );
                double y2 = engineToScrY( wall.getM2().getPosition().getY() );

                g2d.draw( new Line2D.Double(x1, y1, x2, y2) );

                g2d.draw( new Line2D.Double(x1, y1-1, x2, y2-1) );
                g2d.draw( new Line2D.Double(x1, y1+1, x2, y2+1) );

                g2d.draw( new Line2D.Double(x1-1, y1, x2-1, y2) );
                g2d.draw( new Line2D.Double(x1+1, y1, x2+1, y2) );
            }
        }
    }

    public void drawCopySelectedItems()
    {
        //Vec2d offset = new Vec2d(scene.GC.scrToEngineX(CC.MC.mouseLastPos.getX()), scene.GC.scrToEngineY(CC.MC.mouseLastPos.getY()));
        Vec2d offset = new Vec2d(scene.EC.engCursor);
        offset.sub( scene.EC.selectionGroup.getMassCenterVec() );

        g2d.setPaint(Color.GRAY);
        for (Mass mass : scene.EC.selectionGroup.getMassList())
        {
            // aktualne polozenie masy
            double x = engineToScrX( mass.getPosition().getX()+offset.getX() );
            double y = engineToScrY( mass.getPosition().getY()+offset.getY() );
            double r = mass.getMass() *viewScale;
            
            g2d.draw( new Ellipse2D.Double(x-r, y-r, r*2, r*2) );
            g2d.fill( new Ellipse2D.Double(x-r, y-r, r*2, r*2) );
        }

        for (Spring spring : scene.EC.selectionGroup.getSpringList())
        {
            double x1 = engineToScrX( spring.getM1().getPosition().getX()+offset.getX() );
            double y1 = engineToScrY( spring.getM1().getPosition().getY()+offset.getY() );
            double x2 = engineToScrX( spring.getM2().getPosition().getX()+offset.getX() );
            double y2 = engineToScrY( spring.getM2().getPosition().getY()+offset.getY() );

            g2d.draw( new Line2D.Double(x1, y1, x2, y2) );
        }

        for (Wall wall : scene.EC.selectionGroup.getWallList())
        {
            double x1 = engineToScrX( wall.getM1().getPosition().getX()+offset.getX() );
            double y1 = engineToScrY( wall.getM1().getPosition().getY()+offset.getY() );
            double x2 = engineToScrX( wall.getM2().getPosition().getX()+offset.getX() );
            double y2 = engineToScrY( wall.getM2().getPosition().getY()+offset.getY() );

            g2d.draw( new Line2D.Double(x1, y1, x2, y2) );
        }
   }

    private void drawRotation()
    {
        for (Mass mass : scene.EC.transformMassList)
        {
            double x = engineToScrX( mass.getPosition().getX() );
            double y = engineToScrY( mass.getPosition().getY() );
            double r = mass.getMass()+1;

            g2d.setPaint(Color.GRAY);
            g2d.draw( new Ellipse2D.Double(x-r, y-r, r*2, r*2) );
            g2d.fill( new Ellipse2D.Double(x-r, y-r, r*2, r*2) );
        }

        
        double x1 = engineToScrX( CC.MC.mouseVec.getX() );
        double y1 = engineToScrY( CC.MC.mouseVec.getY() );
        double x2 = CC.MC.mouseLastPos.getX();
        double y2 = CC.MC.mouseLastPos.getY();

        g2d.setColor(Color.GRAY);
        g2d.draw( new Line2D.Double(x1,y1, x2,y2));
        g2d.draw( new Line2D.Double(x1,y1, x1+250,y1));
        
    }
    private void drawScaling()
    {
        for (Mass mass : scene.EC.transformMassList)
        {
            double x = engineToScrX( mass.getPosition().getX() );
            double y = engineToScrY( mass.getPosition().getY() );
            double r = mass.getMass()+1;

            g2d.setPaint(Color.GRAY);
            g2d.draw( new Ellipse2D.Double(x-r, y-r, r*2, r*2) );
            g2d.fill( new Ellipse2D.Double(x-r, y-r, r*2, r*2) );
        }
    }

    public void drawBodyActionFrame(Body body)
    {
        // main rect
        g2d.setColor(Color.GREEN);
        g2d.draw( getActionFrameSideBoxRect(body, 0) );

        // scale boxes
        Rectangle2D rect;
        
        for(int i=1; i<9; i++)
        {
            rect = getActionFrameSideBoxRect(body, i);
            g2d.setColor(Color.WHITE);
            g2d.fill( (Rectangle2D.Double) rect);
            g2d.setColor(Color.BLACK);
            g2d.draw( (Rectangle2D.Double) rect);
        }
    }

    public void drawRigidBody(RigidBody rb)
    {

        // boundingBox
        if ( scene.GC.isDrawBoundingBoxes() ) {
            g2d.setColor(SPRINGBODY_BOUNINGBOX_COLOR);
            drawBoundingArea( rb.getBoundingArea() );
        }
        
        int size = rb.dynVecList.size();
        int[] xp = new int[size];
        int[] yp = new int[size];
        for(int i=0; i<size; i++) {
            xp[i] = (int) engineToScrX(rb.dynVecList.get(i).getPosition().x);
            yp[i] = (int) engineToScrY(rb.dynVecList.get(i).getPosition().y);
        }
        g2d.setColor(rb.color);
        g2d.fillPolygon(xp, yp, size);
        g2d.setColor(Color.BLACK);
        g2d.drawPolygon(xp, yp, size);

        Vec2d c = PhysicsHelper.getMassCenterOfMasses(rb.dynVecList);
        Vec2d n = new Vec2d();
        for(int i=0; i<rb.dynVecList.size(); i++) {
            g2d.setColor(Color.GREEN);
            Vec2d v = new Vec2d(rb.dynVecList.get(i).getPosition());
            rb.sceneToBase(v);
            v.makePerp();
            v.scale(rb.omega);
            v.rotate(rb.angle);
            v.add(rb.velocity);
            v.scale(5);
            
            drawEngineArrow( rb.dynVecList.get(i).getPosition(), rb.dynVecList.get(i).getPosition().getAdded(v), 1);

            g2d.setColor(Color.BLACK);
            n.become(rb.dynVecList.get(i).getPosition());
            n.sub(c);
            n.normalize();
            n.scale(10);
            g2d.drawString(""+i, (int) (engineToScrX(rb.dynVecList.get(i).getPosition().x)+n.x), (int) (engineToScrY(rb.dynVecList.get(i).getPosition().y)+n.y));
        }

        // walls
        if (scene.GC.isDrawWalls2d()) {
            Collection<Wall> wCol = rb.border.getWallListSync();
            synchronized(wCol) {
                for(Wall w : wCol) {
                    Vec2d a = w.getCenter();
                    Vec2d b = a.getAdded(w.getNormal().getScaled(15.));
                    g2d.setColor(Color.BLUE);
                    drawEngineArrow( a, b, 1);
                }
            }
        }


//        g2d.setPaint(Color.GREEN);
//        for(Mass m : rb.dynVecList) {
//            double x = engineToScrX( m.getPosition().getX() );
//            double y = engineToScrY( m.getPosition().getY() );
//            double r = m.getMass()+1;
//
//            g2d.fill( new Ellipse2D.Double(x-r, y-r, r*2, r*2) );
//            g2d.draw( new Ellipse2D.Double(x-r, y-r, r*2, r*2) );
//        }
//
//        g2d.setPaint(Color.RED);
//        for(Vec2d v : rb.baseVecList) {
//            double x = engineToScrX( v.getX() );
//            double y = engineToScrY( v.getY() );
//            double r = 2;
//
//            g2d.fill( new Ellipse2D.Double(x-r, y-r, r*2, r*2) );
//            g2d.draw( new Ellipse2D.Double(x-r, y-r, r*2, r*2) );
//        }
    }
////////////////////////////////////////////////////////////////////////////////
//                       G R A P H I C   P A N E L                            //
////////////////////////////////////////////////////////////////////////////////

    public double getViewScale() {
        return viewScale;
    }
    public double getTranslateX() {
        return this.ltvpdX;
    }
    public double getTranslateY() {
        return this.ltvpdY;
    }

    public void setViewScale(double viewScale) {
        this.viewScale = viewScale;
    }

    public void resizeToFitViewScale() {
        if ( viewScale == 1.0 ) {
            this.setSize(originalSize);
            this.setMaximumSize(originalSize);
            this.setPreferredSize(originalSize);
            this.setMinimumSize(originalSize);
            this.ltvpdX = dX;
            this.ltvpdY = dY;
        }
        else if ( viewScale < 1) {
            Dimension fixedSize = new Dimension((int)Math.ceil( scene.getJETContext().getMainBound().getWidth()*viewScale+1 + 2*dX* viewScale),
                                                (int)Math.ceil( scene.getJETContext().getMainBound().getHeight()*viewScale+1 + 2*dY*viewScale)
                                    );
            this.setSize(fixedSize);
            this.setMaximumSize(fixedSize);
            this.setPreferredSize(fixedSize);
            this.setMinimumSize(fixedSize);

            JViewport viewport = (JViewport)getParent();

            if ( Math.ceil(scene.getJETContext().getMainBound().getWidth()*viewScale+1 + 2*dX* viewScale) < viewport.getWidth() ||
                 Math.ceil(scene.getJETContext().getMainBound().getHeight()*viewScale+1 + 2*dY*viewScale) < viewport.getHeight() )
            {
//                double newWidth = sPane.getViewport().getWidth()*2 + Math.ceil( scene.getEngine().getMainBound().getWidth()*viewScale+1 );
//                double newHeight = sPane.getViewport().getHeight()*2 + Math.ceil( scene.getEngine().getMainBound().getHeight()*viewScale+1 );

                double newWidth = viewport.getWidth() + Math.ceil( scene.getJETContext().getMainBound().getWidth()*viewScale+1 );
                double newHeight = viewport.getHeight() + Math.ceil( scene.getJETContext().getMainBound().getHeight()*viewScale+1 );

                Dimension newSize = new Dimension( (int)newWidth, (int)newHeight );
                System.out.println("width<... newSize= "+newSize);
                this.setSize( newSize );this.setMaximumSize(newSize);
                this.setMinimumSize(newSize);this.setPreferredSize(newSize);

                ltvpdX = (this.getWidth() - scene.getJETContext().getMainBound().getWidth()*viewScale+1) /2 ;
                ltvpdY = (this.getHeight() - scene.getJETContext().getMainBound().getHeight()*viewScale+1) /2 ;
            }
            else {
                ltvpdX = dX * viewScale;
                ltvpdY = dY * viewScale;
            }
        }
        else if ( viewScale > 1 ) {
            Dimension fixedSize = new Dimension((int)Math.ceil( scene.getJETContext().getMainBound().getWidth()*viewScale+1 + 2*dX* viewScale),
                                                (int)Math.ceil( scene.getJETContext().getMainBound().getHeight()*viewScale+1 + 2*dY*viewScale)
                                    );
            this.setSize(fixedSize);
            this.setMaximumSize(fixedSize);
            this.setPreferredSize(fixedSize);
            this.setMinimumSize(fixedSize);
            ltvpdX = dX * viewScale;
            ltvpdY = dY * viewScale;
        }
    }
    public double engineToScrX(double x) {
        return x * viewScale + this.ltvpdX;
    }
    public double engineToScrY(double y) {
        return fixVertical( y*viewScale ) - this.ltvpdY;
    }
    public Vec2d engineToScrVec(Vec2d vec) {
        return new Vec2d( engineToScrX(vec.getX()), engineToScrY(vec.getY()));
    }

    public double scrToEngineX(double x) {
        return  (x-this.ltvpdX)/viewScale;
    }
    public double scrToEngineY(double y) {
        return fixVertical( y+this.ltvpdY )/viewScale ;
    }
    public Vec2d scrToEngineVec(Vec2d vec) {
        return new Vec2d( scrToEngineX(vec.getX()), scrToEngineY(vec.getY()));
    }
    public double monitorToScrX(double mx) {
        return -(this.getLocationOnScreen().getX() - mx);
    }
    public double monitorToScrY(double my) {
        return -(this.getLocationOnScreen().getY() - my);
    }
    public double monitorToEngineX(double mx) {
        return scrToEngineX( monitorToScrX(mx) );
    }
    public double monitorToEngineY(double my) {
        return scrToEngineY( monitorToScrY(my) );
    }
    public GraphicMode getGraphicMode() {
        return GraphicMode.Swing;
    }


    /*
    public TabType getTabType() {
        return TabType.GraphicPanel;
    }

    public String getTitle() {
        return "Scene [Swing]";
    }
    */

    public String getSceneName() {
        return scene.getName();
    }

    private void drawSceneDrawables() {
        Collection<SceneDrawable> dCol = scene.GC.getSceneDrawablesSync();
        synchronized(dCol) {
            for(SceneDrawable sd : dCol)
                sd.draw(g2d, this);
        }
    }
}
